package com.monolithiot.sso.service.impl;

import com.monolithiot.sso.common.entity.DeviceAuthorization;
import com.monolithiot.sso.common.entity.User;
import com.monolithiot.sso.common.exception.ServiceUnforeseenException;
import com.monolithiot.sso.common.util.AuthorizationUtil;
import com.monolithiot.sso.common.util.DateUtil;
import com.monolithiot.sso.common.util.IdentityUtil;
import com.monolithiot.sso.dao.BaseMapper;
import com.monolithiot.sso.dao.mapper.DeviceAuthorizationMapper;
import com.monolithiot.sso.service.DeviceAuthorizationService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.validation.constraints.NotNull;
import java.util.Date;
import java.util.List;

/**
 * 2018/12/22 Create by 郭文梁
 * DeviceAuthorizationServiceImpl
 * 设备授权业务实现
 *
 * @author 郭文梁
 * @date 2018/12/22
 */
@Slf4j
@Service
public class DeviceAuthorizationServiceImpl extends BaseServiceImpl<DeviceAuthorization> implements DeviceAuthorizationService {
    private final DeviceAuthorizationMapper deviceAuthorizationMapper;

    @Autowired
    public DeviceAuthorizationServiceImpl(DeviceAuthorizationMapper deviceAuthorizationMapper) {
        this.deviceAuthorizationMapper = deviceAuthorizationMapper;
    }

    @Override
    BaseMapper<DeviceAuthorization> getMapper() {
        return deviceAuthorizationMapper;
    }

    @Override
    public DeviceAuthorization auth(User user, int expireIn, Integer deviceType, String serialNumber) {
        DeviceAuthorization query = new DeviceAuthorization();
        query.setUserId(user.getId());

        DeviceAuthorization authorization = deviceAuthorizationMapper.selectOne(query);
        if (authorization == null) {
            authorization = createNewAuthorization(user, expireIn, deviceType, serialNumber);
        } else if (AuthorizationUtil.isOverdue(authorization)) {
            int res = deviceAuthorizationMapper.deleteByPrimaryKey(authorization.getId());
            if (res != 1) {
                throw new ServiceUnforeseenException("Could not delete overdue authorization, res=" + res);
            }
            log.debug("{} overdue authorization has been deleted!");
            authorization = createNewAuthorization(user, expireIn, deviceType, serialNumber);
        }
        authorization.setUser(user);
        return authorization;
    }

    @Override
    public DeviceAuthorization findByDeviceTypeAndTokenWithUser(Integer deviceType, String token) {
        DeviceAuthorization query = new DeviceAuthorization();
        query.setToken(token);
        query.setDeviceTypeId(deviceType);

        List<DeviceAuthorization> authorizations = deviceAuthorizationMapper.selectFetchAll(query);
        DeviceAuthorization res = authorizations == null || authorizations.size() != 1 ? null : authorizations.get(0);
        if (res == null || AuthorizationUtil.isOverdue(res)) {
            return null;
        }
        return res;
    }

    @Override
    public int deleteOverdue() {
        return deviceAuthorizationMapper.deleteOverdue();
    }

    @Override
    public DeviceAuthorization findByToken(String token) {
        DeviceAuthorization query = new DeviceAuthorization();
        query.setToken(token);
        return deviceAuthorizationMapper.selectOne(query);
    }

    @Override
    public DeviceAuthorization setName(String token, String name) {
        DeviceAuthorization authorization = findByToken(token);
        if (authorization == null) {
            return null;
        }
        authorization.setDeviceName(name);
        return update(authorization);
    }

    @Override
    public List<DeviceAuthorization> findByUser(User user) {
        DeviceAuthorization query = new DeviceAuthorization();
        query.setUserId(user.getId());
        return deviceAuthorizationMapper.select(query);
    }

    @Override
    public List<DeviceAuthorization> findByUserFetchAll(User user) {
        DeviceAuthorization query = new DeviceAuthorization();
        query.setUserId(user.getId());
        return deviceAuthorizationMapper.selectFetchAll(query);
    }

    /**
     * 创建新的授权
     *
     * @param user         被授权用户
     * @param expireIn     授权时间
     * @param deviceType   设备类型
     * @param serialNumber 序列号
     * @return 授权对象
     */
    @NotNull
    private DeviceAuthorization createNewAuthorization(User user, int expireIn, Integer deviceType, String serialNumber) {
        Date now = DateUtil.now();
        DeviceAuthorization authorization = new DeviceAuthorization();
        authorization.setUserId(user.getId());
        authorization.setDeviceTypeId(deviceType);
        authorization.setToken(IdentityUtil.randomPrettyUUID());
        authorization.setCreateTime(now);
        authorization.setLastActivityTime(now);
        authorization.setExpireIn(expireIn);
        authorization.setSerialNumber(serialNumber);
        DeviceAuthorization res = save(authorization);
        if (res == null) {
            throw new ServiceUnforeseenException("Could not save Authorization : " + authorization);
        }
        return res;
    }
}
